Leer hoe u React Error Boundaries met hooks implementeert om laadfouten van hulpbronnen elegant af te handelen, wat de gebruikerservaring en applicatiestabiliteit verbetert.
Robuust Laden van Hulpbronnen in React: Error Boundaries met Hooks Beheersen
In moderne webapplicaties is het asynchroon laden van hulpbronnen een gangbare praktijk. Of het nu gaat om het ophalen van data van een API, het laden van afbeeldingen of het importeren van modules, het correct afhandelen van potentiële fouten tijdens het laden van hulpbronnen is cruciaal voor een soepele gebruikerservaring. React Error Boundaries bieden een mechanisme om JavaScript-fouten overal in hun onderliggende componentenboom op te vangen, deze fouten te loggen en een terugval-UI (fallback UI) weer te geven in plaats van de hele applicatie te laten crashen. Dit artikel onderzoekt hoe u Error Boundaries effectief kunt gebruiken in combinatie met React Hooks om fouten bij het laden van hulpbronnen te beheren.
Error Boundaries Begrijpen
Vóór React 16 konden onafgehandelde JavaScript-fouten tijdens het renderen van componenten de interne staat van React corrumperen en cryptische fouten veroorzaken bij volgende renders. Error Boundaries lossen dit op door te fungeren als 'catch-all' blokken voor fouten die optreden in hun onderliggende componenten. Het zijn React-componenten die een of beide van de volgende lifecycle-methoden implementeren:
static getDerivedStateFromError(error): Deze statische methode wordt aangeroepen nadat een fout is opgetreden in een onderliggend component. Het ontvangt de opgetreden fout als argument en retourneert een waarde om de staat van het component bij te werken.componentDidCatch(error, info): Deze lifecycle-methode wordt aangeroepen nadat een fout is opgetreden in een onderliggend component. Het ontvangt de opgetreden fout als argument, evenals een object met informatie over welk component de fout heeft veroorzaakt. U kunt dit gebruiken om foutinformatie te loggen.
Belangrijk is dat Error Boundaries alleen fouten opvangen in de renderfase, in lifecycle-methoden en in constructors van de hele boom eronder. Ze vangen geen fouten op voor:
- Event handlers (lees meer in de sectie hieronder)
- Asynchrone code (bijv.
setTimeoutofrequestAnimationFramecallbacks) - Server-side rendering
- Fouten die in de Error Boundary zelf worden gegooid (in plaats van in de onderliggende componenten)
Error Boundaries en React Hooks: Een Krachtige Combinatie
Hoewel class-componenten traditioneel werden gebruikt om Error Boundaries te implementeren, bieden React Hooks een beknoptere en functionelere aanpak. We kunnen een herbruikbare useErrorBoundary hook maken die de logica voor foutafhandeling inkapselt en een handige manier biedt om componenten te wrappen die mogelijk fouten veroorzaken tijdens het laden van hulpbronnen.
Een Aangepaste useErrorBoundary Hook Maken
Hier is een voorbeeld van een useErrorBoundary hook:
import { useState, useCallback } from 'react';
function useErrorBoundary() {
const [error, setError] = useState(null);
const resetError = useCallback(() => {
setError(null);
}, []);
const captureError = useCallback((e) => {
setError(e);
}, []);
const ErrorBoundary = useCallback(({ children, fallback }) => {
if (error) {
return fallback ? fallback : Er is een fout opgetreden: {error.message || String(error)};
}
return children;
}, [error]);
return { ErrorBoundary, captureError, error, resetError };
}
export default useErrorBoundary;
Uitleg:
useState: We gebruikenuseStateom de foutstatus te beheren. De fout wordt aanvankelijk opnullgezet.useCallback: We gebruikenuseCallbackom de functiesresetErrorencaptureErrorte memoïseren. Dit is een goede gewoonte om onnodige re-renders te voorkomen als deze functies als props worden doorgegeven.ErrorBoundaryComponent: Dit is een functioneel component gemaakt metuseCallbackdatchildrenen een optionelefallbackprop accepteert. Als er een fout in de staat aanwezig is, rendert het ofwel het opgegevenfallbackcomponent of een standaard foutmelding. Anders rendert het de children. Dit fungeert als onze Error Boundary. De dependency array `[error]` zorgt ervoor dat het opnieuw rendert wanneer de `error`-staat verandert.captureErrorFunctie: Deze functie wordt gebruikt om de foutstatus in te stellen. U roept deze aan binnen eentry...catchblok bij het laden van hulpbronnen.resetErrorFunctie: Deze functie wist de foutstatus, waardoor het component zijn children opnieuw kan renderen (en mogelijk de laadpoging van de hulpbron opnieuw kan proberen).
Hulpbronnen Laden met Foutafhandeling Implementeren
Laten we nu kijken hoe we deze hook kunnen gebruiken om laadfouten van hulpbronnen af te handelen. Beschouw een component dat gebruikersgegevens ophaalt van een API:
import React, { useState, useEffect } from 'react';
import useErrorBoundary from './useErrorBoundary';
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
const { ErrorBoundary, captureError, error, resetError } = useErrorBoundary();
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch(`https://api.example.com/users/${userId}`);
if (!response.ok) {
throw new Error(`HTTP-fout! status: ${response.status}`);
}
const data = await response.json();
setUser(data);
} catch (e) {
captureError(e);
}
};
fetchData();
}, [userId, captureError]);
if (error) {
return (
Kon gebruikersdata niet laden. {user.name}
Email: {user.email}
{/* Andere gebruikersdetails */}Uitleg:
- We importeren de
useErrorBoundaryhook. - We roepen de hook aan om het
ErrorBoundarycomponent, decaptureErrorfunctie, deerrorstaat en deresetErrorfunctie te verkrijgen. - Binnen de
useEffecthook, wrappen we de API-aanroep in eentry...catchblok. - Als er een fout optreedt tijdens de API-aanroep, roepen we
captureError(e)aan om de foutstatus in te stellen. - Als de
errorstaat is ingesteld, renderen we hetErrorBoundarycomponent. We geven een aangepastefallbackprop mee die een foutmelding en een "Opnieuw proberen"-knop toont. Door op de knop te klikken, wordtresetErroraangeroepen om de foutstatus te wissen, wat een re-render en een nieuwe poging om de data op te halen teweegbrengt. - Als er geen fout is opgetreden en de gebruikersdata is geladen, renderen we de gebruikersprofiel details.
Verschillende Soorten Laadfouten van Hulpbronnen Afhandelen
Verschillende soorten laadfouten van hulpbronnen kunnen verschillende afhandelingsstrategieën vereisen. Hier zijn enkele veelvoorkomende scenario's en hoe u ze kunt aanpakken:
Netwerkfouten
Netwerkfouten treden op wanneer de client geen verbinding kan maken met de server (bijv. door een netwerkstoring of downtime van de server). Het bovenstaande voorbeeld handelt al basisnetwerkfouten af met `response.ok`. U kunt overwegen om meer geavanceerde foutdetectie toe te voegen, bijvoorbeeld:
//Binnen de fetchData-functie
try {
const response = await fetch(`https://api.example.com/users/${userId}`);
if (!response.ok) {
// Overweeg specifieke foutcode-afhandeling toe te voegen
if (response.status === 404) {
throw new Error("Gebruiker niet gevonden");
} else if (response.status >= 500) {
throw new Error("Serverfout. Probeer het later opnieuw.");
} else {
throw new Error(`HTTP-fout! status: ${response.status}`);
}
}
const data = await response.json();
setUser(data);
} catch (error) {
if (error.message === 'Failed to fetch') {
// Waarschijnlijk een netwerkfout
captureError(new Error('Netwerkfout. Controleer uw internetverbinding.'));
} else {
captureError(error);
}
}
In dit geval kunt u een bericht aan de gebruiker tonen dat er een probleem is met de netwerkverbinding en suggereren dat ze hun internetverbinding controleren.
API-fouten
API-fouten treden op wanneer de server een foutreactie retourneert (bijv. een 400 Bad Request of een 500 Internal Server Error). Zoals hierboven getoond, kunt u `response.status` controleren en deze fouten op de juiste manier afhandelen.
Data Parsing Fouten
Data parsing fouten treden op wanneer de respons van de server niet in het verwachte formaat is en niet kan worden geparst (bijv. ongeldige JSON). U kunt deze fouten afhandelen door de response.json() aanroep in een try...catch blok te wrappen:
//Binnen de fetchData-functie
try {
const response = await fetch(`https://api.example.com/users/${userId}`);
if (!response.ok) {
throw new Error(`HTTP-fout! status: ${response.status}`);
}
const data = await response.json();
setUser(data);
} catch (error) {
if (error instanceof SyntaxError) {
captureError(new Error('Parseren van data van de server mislukt.'));
} else {
captureError(error);
}
}
Afbeelding Laadfouten
Voor het laden van afbeeldingen kunt u de onError event handler op de <img> tag gebruiken:
function MyImage({ src, alt }) {
const { ErrorBoundary, captureError } = useErrorBoundary();
const [imageLoaded, setImageLoaded] = useState(false);
const handleImageLoad = () => {
setImageLoaded(true);
};
const handleImageError = (e) => {
captureError(new Error(`Laden van afbeelding mislukt: ${src}`));
};
return (
Afbeelding laden mislukt.